package es.uji.viselab.network;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import es.uji.viselab.LogLevel;
import es.uji.viselab.LogRecorder;
import es.uji.viselab.ViSeLabException;

public class Server extends Network implements Runnable{
	
	
	int port;
	// http://www.ase.md/~aursu/ClientServerThreads.html
	static final int maxClientsCount = 5;
	private static final networkServerThread[] threads = new networkServerThread[maxClientsCount];

	ServerSocket welcomeSocket = null;

	public Server(EncoderDecoder ec, int port) {
		super(ec);
		this.port = port;
	}

	
	public void startServer() throws ViSeLabException {
		try {
			int port = 10100;
			welcomeSocket = new ServerSocket(port);
			LogRecorder.log(LogLevel.INFO, "TCP Server started at port " + port);
			LogRecorder.log(LogLevel.INFO, "Server waiting for incoming connection");
			socket = welcomeSocket.accept();
			LogRecorder.log(LogLevel.INFO, "New connection accepted from "
					+ socket.getInetAddress().getHostAddress());

			int i;
			// look for the next thread slot free
			for (i = 0; i < maxClientsCount; i++) {
				if (threads[i] == null) {
					networkServerThread nst = new networkServerThread(this, threads);
					notifyNewClient(nst);
					threads[i] = nst;
					nst.start();
					break;
				}
			}
			if (i == maxClientsCount) {
				LogRecorder.log(LogLevel.ERROR, "Server busy", "Server.start();");
				throw new ViSeLabException("Server busy");
			}

		} catch (IOException e) {
			LogRecorder.log(LogLevel.ERROR, "Server busy","Server.stat();");
			throw new ViSeLabException(e.getMessage(), "Server.start()");
		}
	}

	public void closeServer() throws ViSeLabException {
		try {
			welcomeSocket.close();
			LogRecorder.log(LogLevel.INFO, "Server is no longer listening");
		} catch (IOException e) {
			throw new ViSeLabException("Error when clossing the connection",e.getMessage());
		}
	}
	
	public void closeConnection() throws ViSeLabException {
			super.close();
	}

	public Socket getServiceSocket() {
         return super.getServiceSocket();
	}

	@Override
	public void run() {
		try {
			startServer();
		} catch (ViSeLabException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	void notifyNewClient(networkServerThread nst){
		Iterator<NetworkListener> iterator= eventListeners.iterator();
		while (iterator.hasNext()){
			NetworkListener nl=iterator.next();
			nl.newClient(nst);
		}
	}


	
}
